class Repository < ActiveRecord::Base

	require 'fileutils'
	require 'svn/client'
	require 'svn/ra'

	before_create		:load_repository
	before_create		:create_repository
	before_destroy	:remove_repository

	validates_uniqueness_of :name, :if => :name_required
  validates_length_of :name, :within => 1..32, :if => :name_required
  validates_format_of	:name, :with => /^[_a-zA-Z0-9]+$/, :if => :name_required

	# validates_uniqueness_of :path, :if => :path_required
	# validates_presence_of :path, :if => :path_required

	has_many :memberships, :dependent => :destroy
	has_many :members, :through => :memberships, :source => :user
	has_many :notes, :dependent => :destroy

	attr_accessor :dumped_repository, :dumped_project_name

	def latest_revision
		repo = Svn::Repos.open(self.path)

		history = repo.fs.history("/", 0, repo.fs.youngest_rev)
		revision = (history.size.zero?) ? 0 : history.first[1]
	end

	def backup
		FileUtils.mkdir_p BACKUP_ROOT unless File.exist?(BACKUP_ROOT)
		filename = "#{self.name}_#{Time.now.to_i}"
		%x(svnadmin dump #{self.path} > #{BACKUP_ROOT}/#{filename})
		"#{BACKUP_ROOT}/#{filename}"
	end

	def svn_url(user = nil)
		user_login = (user.blank?) ? "&lt;your account&gt;" : user.login
		"#{SVN_PROTOCOL}://#{BASE_DOMAIN}#{REPOSITORY_ROOT}/#{self.name}/trunk"
	end

	def clear_membership
		self.memberships.each {|ms| ms.destroy}
	end

	def create_member(u)
		user = (u.class == User) ? u : User.find_by_login(u)
		membership = self.memberships.new(:user_id => user.id)
		membership.save
	end

	def update_svn_password
		text = ["[users]", "#{ADMIN_LOGIN} = #{ADMIN_PASSWORD}"]
		members.each do |m|
			text.push("#{m.login} = #{CustCrypt::decrypt(m.svn_phrase, m.salt)}")
		end

		File.open("#{self.path}/conf/passwd", 'wb') {|f| f.write(text.join("\n"))}
	end

	protected
		def name_required
			dumped_repository.blank?
		end

		def load_repository
			return unless self.name.blank?
			return false if dumped_repository.blank?

			temporary_filename = Time.now.to_i.to_s
			temporary_filepath = "/tmp/#{temporary_filename}"
			File.open(temporary_filepath, 'wb') {|f| f.write(dumped_repository.read) }

			self.name = dumped_project_name || dumped_repository.original_filename.split(".").first
			repository_path = self.path = "#{REPOSITORY_ROOT}/#{self.name}"
			return false if File.exists?(repository_path)
			%x(svnadmin create --fs-type fsfs #{repository_path})
			%x(cat #{REPOSITORY_CONF}/svnserve.conf > #{repository_path}/conf/svnserve.conf)
			%x(cat #{REPOSITORY_CONF}/passwd > #{repository_path}/conf/passwd)

			spawn do
				system("svnadmin load #{repository_path} < #{temporary_filepath} &> /tmp/load_log_#{self.name}")
			end
		end

		def create_repository
			return unless self.path.blank?

			# %x(svnadmin create #{REPOSITORY_ROOT}/#{self.name})
			repository_path = self.path = "#{REPOSITORY_ROOT}/#{self.name}"
			%x(svnadmin create --fs-type fsfs #{repository_path})
			%x(svn mkdir file://#{repository_path}/branches -m "create branch directory by default" --force-log)
			%x(svn mkdir file://#{repository_path}/tags -m "create tag directory by default" --force-log)
			%x(svn mkdir file://#{repository_path}/trunk -m "create trunk directory by default" --force-log)
			%x(cat #{REPOSITORY_CONF}/svnserve.conf > #{repository_path}/conf/svnserve.conf)
			%x(cat #{REPOSITORY_CONF}/passwd > #{repository_path}/conf/passwd)
			# %x(echo #{ADMIN_PASS} | sudo -S chown -R #{ADMIN_LOGIN}:#{USER_GROUP} #{REPOSITORY_ROOT}/#{self.name})
			# %x(echo #{ADMIN_PASS} | sudo -S chmod -R g+w #{REPOSITORY_ROOT}/#{self.name})

			# %x(cp -R #{REPOSITORY_ROOT}/template #{REPOSITORY_ROOT}/#{self.name})
		end

		def remove_repository
			# %x(echo #{ADMIN_PASSWORD} | sudo -S rm -rf #{REPOSITORY_ROOT}/#{self.name})

			return unless File.exists?(self.path)
			%x(rm -rf #{self.path})
		end
end
